<?php
/**
 * @author Thibaut Cromphaut, Gaïtano Boeraeve, Mathias Helin, Dimitry Dierickx
 * @copyright  Copyright (c) 2011 Artevelde University College Ghent 
 */

class CourseController extends Zend_Controller_Action
{
    private $_redirector = null;
    
    private $_allcourses_page_limit     = 10;
    private $_mycourses_page_limit      = 10;
    private $_announces_page_limit      = 5;
    private $_books_page_limit          = 8;
    private $_recentcourses_page_limit  = 10;
    private $_recent_courses_days       = 30;
    
    public function init()
    {
        $this->_redirector = $this->_helper->getHelper('Redirector');
        $this->stylesBase  = $this->view->baseUrl() . '/styles/';
    }
    
    /**
     * This will validate our session and the requested action;
     */
    public function preDispatch()
    {
        // Check our identity
        if(Zend_Auth::getInstance()->hasIdentity())
        {
            // Check the requestion action
            switch ( $this->getRequest()->getActionName())
            {
                case 'index':
                case 'search':
                case 'edit':
                case 'add':
                case 'delete':
                case 'submit':
                case 'follow':
                case 'addbook':
                case 'addannouncement':
                case 'stopfollow':
                case 'ajaxrequest':
                case 'view':
                    // -- These actions are allowed, nothing to do -- //
                    break;
                default:
                    // -- Invalid action requested, refer to homepage -- //
                    $this->_helper->redirector('index', 'index');
                    break;
            }
        }
        else
        {
            // -- No session, refer to loginpage -- //
            $this->_helper->redirector('login', 'user');
        }
    }
    
    /**
     * This action will handle all ajax-requests
     */
    public function ajaxrequestAction()
    {
        // Disable the layout
        $this->_helper->layout()->disableLayout();
        $this->_helper->viewRenderer->setNoRender(true);
        
        // Get current user
        $user   = Zend_Auth::getInstance()->getStorage()->read();
        
        // These are default pager variables
        $current_page   = (string)$this->getRequest()->getParam('p');
        $pager_base     = $this->getRequest()->getBaseUrl()."/index/index/";
        
        // Get the request and do something accordingly
        $request  = (string)$this->getRequest()->getParam('req');
        switch($request)
        {
            case "pageallcourses":
                $pager_var      = "cp";
                $html[]         = $this->_loopPartial('courses-block-course', $this->_getCourses($current_page, $this->_allcourses_page_limit), array('user' => $user));
                $html[]         = $this->_fetchPager($current_page, ($this->_countCourses()/$this->_allcourses_page_limit), $pager_base, $pager_var);
                $result         = implode("\n", $html);
                break;
            case "pagemycourses":
                $pager_var      = "mp";
                $html[]         = $this->_loopPartial('courses-block-course', $this->_getCoursesByUserId($user->Id, $current_page, $this->_mycourses_page_limit), array('user' => $user));
                $html[]         = $this->_fetchPager($current_page, ($this->_countCoursesByUserId($user->Id)/$this->_mycourses_page_limit), $pager_base, $pager_var);
                $result         = implode("\n", $html);
                break;
            case "pagerecentcourses":
                $pager_var      = "rp";
                $html[]         = $this->_loopPartial('courses-block-course', $this->_getCoursesByRecent($this->_recent_courses_days, $current_page, $this->_recentcourses_page_limit), array('user' => $user));
                $html[]         = $this->_fetchPager($current_page, ($this->_countCoursesByRecent($this->_recent_courses_days)/$this->_recentcourses_page_limit), $pager_base, $pager_var);
                $result         = implode("\n", $html);
                break;
            case "pageannounces":
                $course_id      = (string)$this->getRequest()->getParam('id');
                $pager_var      = "ap";
                $html[]         = $this->_loopPartial('block-announcement', $this->_getAnnouncementsByCourseId($course_id, $current_page, $this->_announces_page_limit));
                $html[]         = $this->_fetchPager($current_page, ($this->_countAnnouncementsByCourseId($course_id)/$this->_announces_page_limit), $pager_base, $pager_var);
                $result         = implode("\n", $html);
                break;
            case "pagebooks":
                $course_id      = (string)$this->getRequest()->getParam('id');
                $pager_var      = "bp";
                $html[]         = $this->_loopPartial('books-block-book', $this->_getBooksByCourseId($course_id, $current_page, $this->_books_page_limit));
                $html[]         = $this->_fetchPager($current_page, ($this->_countBooksByCourseId($course_id)/$this->_books_page_limit), $pager_base, $pager_var);
                $result         = implode("\n", $html);
                break;
            default:
                $result = false;
                break;
        }
        
        // output result
        echo $result; 
    }

    /**
     * This is the main action.
     * It will display the All courses, My courses and New courses page-tabs
     */
    public function indexAction()
    {
        // Set up the view
        $view   = $this->_getView('Courses');
        // Get the logged in User-object, and get other 
        
        $user   = Zend_Auth::getInstance()->getStorage()->read();
        // Pass some variables to our view
        $view->user     = $user;
        // Pager variables
        $pager_base     = $this->getRequest()->getBaseUrl()."/course/index/";
        // Set ALL COURSES block
        $crse_count         = $this->_countCourses();
        
        
        if($crse_count > 0)
        {
            $crse_pager_var     = "cp";
            $crse_current_page  = (string)$this->getRequest()->getParam($crse_pager_var);
            $crse_current_page  = ($crse_current_page > 0 ? $crse_current_page : 1);
            $view->crse_partial = $this->_loopPartial('courses-block-course', $this->_getCourses($crse_current_page, $this->_allcourses_page_limit), array('user' => $user));
            $view->crse_pager   = $this->_fetchPager($crse_current_page, ($crse_count/$this->_allcourses_page_limit), $pager_base, $crse_pager_var);
        }
        else
        {
            $view->crse_partial = "<p>There are no current courses added to our website. Please check again soon.</p>";
            $view->crse_pager   = null;
        }
        // Set MY COURSES block
        $mycr_count         = $this->_countCoursesByUserId($user->Id);
        if($mycr_count > 0)
        {
            $mycr_pager_var     = "mp";
            $mycr_current_page  = (string)$this->getRequest()->getParam($mycr_pager_var);
            $mycr_current_page  = ($mycr_current_page > 0 ? $mycr_current_page : 1);
            $view->mycr_partial = $this->_loopPartial('courses-block-course', $this->_getCoursesByUserId($user->Id, $mycr_current_page, $this->_mycourses_page_limit), array('user' => $user));
            $view->mycr_pager   = $this->_fetchPager($mycr_current_page, ($mycr_count/$this->_mycourses_page_limit), $pager_base, $mycr_pager_var);
        }
        else
        {
            $view->mycr_partial = $view->partial('partials/add-course.phtml', array());
            $view->mycr_pager   = null;
        }
        // Set RECENT COURSES block
        $rccr_count         = $this->_countCoursesByRecent($this->_recent_courses_days);
        if($rccr_count > 0)
        {
            $rccr_pager_var     = "mp";
            $rccr_current_page  = (string)$this->getRequest()->getParam($rccr_pager_var);
            $rccr_current_page  = ($rccr_current_page > 0 ? $rccr_current_page : 1);
            $view->rccr_partial = $this->_loopPartial('courses-block-course', $this->_getCoursesByRecent($this->_recent_courses_days, $rccr_current_page, $this->_recentcourses_page_limit), array('user' => $user));
            $view->rccr_pager   = $this->_fetchPager($rccr_current_page, ($rccr_count/$this->_recentcourses_page_limit), $pager_base, $rccr_pager_var);
        }
        else
        {
            $view->rccr_partial = "<p>There are no new courses add to our website in the last ".$this->_recent_courses_days." days.</p>";
            $view->rccr_pager   = null;
        }
    }
    
    /**
     * This will let a user follow a course
     *
     */
    public function followAction()
    {
        $user   = Zend_Auth::getInstance()->getStorage()->read();
        $id     = (string)$this->getRequest()->getParam('id');
        $this->_addCourseToFollowList($id, $user->Id);
        // Redirect to book
        $this->_redirector->gotoSimple(
                               'view',
                               'course',
                               null,
                               array('id' => $id)
        );
    }
    
    /**
     * This will let a user delete a course from his follow list
     *
     */
    public function stopfollowAction()
    {
        $user   = Zend_Auth::getInstance()->getStorage()->read();
        $id     = (string)$this->getRequest()->getParam('id');
        $this->_removeCourseFromFollowList($id, $user->Id);
        // Redirect to book index
        $this->_redirector->gotoSimple(
                               'index',
                               'course',
                               null,
                               array()
        );
    }
    
    /**
     * Display the view course page
     */
    public function viewAction()
    {
        // Get some vars
        $course_id  = (string)$this->getRequest()->getParam('id');
        // Set up the view
        $view   = $this->_getView('View course');
        // Get the logged in User-object, and get other 
        $user   = Zend_Auth::getInstance()->getStorage()->read();
        $course = $this->_getCourseById($course_id);
        // Pass some variables to our view
        $view->user     = $user;
        $view->course   = $course;
        // Pager variables
        $pager_base     = $this->getRequest()->getBaseUrl()."/course/view/id/".$course_id."/";
        // Set ANNOUNCEMENTS block
        $annc_count         = $this->_countAnnouncementsByCourseId($course_id);
        if($annc_count > 0)
        {
            $annc_pager_var     = "ap";
            $annc_current_page  = (string)$this->getRequest()->getParam($annc_pager_var);
            $annc_current_page  = ($annc_current_page > 0 ? $annc_current_page : 1);
            $view->annc_partial = $this->_loopPartial('block-announcement', $this->_getAnnouncementsByCourseId($course_id, $annc_current_page, $this->_announces_page_limit));
            $view->annc_pager   = $this->_fetchPager($annc_current_page, ($annc_count/$this->_announces_page_limit), $pager_base, $annc_pager_var);
        }
        else
        {
            $view->annc_partial = "<p>There are no current announcements for this course.</p>";
            $view->annc_pager   = null;
        }
        // Set BOOKS block
        $book_count             = $this->_countBooksByCourseId($course_id);
        if($book_count > 0)
        {
            $book_pager_var     = "bp";
            $book_current_page  = (string)$this->getRequest()->getParam($book_pager_var);
            $book_current_page  = ($book_current_page > 0 ? $book_current_page : 1);
            $view->book_partial = $this->_loopPartial('books-block-book', $this->_getBooksByCourseId($course_id, $book_current_page, $this->_books_page_limit));
            $view->book_pager   = $this->_fetchPager($book_current_page, ($book_count/$this->_books_page_limit), $pager_base, $book_pager_var);
        }
        else
        {
            $view->book_partial = "<p>There are no current books for this course.</p>";
            $view->book_pager   = null;
        }
        // Rewrite breadcrumb
        $page_crse   = $view->navigation()->getContainer()->findOneByLabel('View course');
        $page_crse->setLabel($view->course->Name)->setParams(array('id' => $view->course->Id));
    }
    
    /**
     * Search for user input
     */
    public function searchAction()
    {
        $this->_helper->layout()->disableLayout();
        $this->_helper->viewRenderer->setNoRender(true);
        
        $result  = array();
        $courses = $this->_getCoursesByName($this->_getParam('searchstring'));           
        
        if($courses)
        {
            foreach($courses as $course) {            
                $result[] = $course->Name;
            }
        }
        
        $this->_helper->json($result);
    }
        
    /**
     * Add a course
     */
    public function addAction()
    {           
        $view = $this->_getView('Add Course');
        $form = $this->_getAddCourseForm(); 
        
        if($this->getRequest()->isPost()) 
	{                       
            $formData  = $this->_request->getPost();
                        
            if($form->isValid($formData)) 
            {                
               $this->_saveForm($form);
            }
        }
        
        $view->form = $form;       
    }
    
    /**
     * Add a book to course
     */
    public function addbookAction()
    {           
        $view = $this->_getView('Add existing book');
        $form = $this->_getAddBookToCourseForm(); 
        $course_id  = (string)$this->getRequest()->getParam('id');
        if($this->getRequest()->isPost()) 
	{                       
            $formData  = $this->_request->getPost();
            $course_id = $formData['course_id'];
            if($form->isValid($formData)) 
            {
                $view   = $this->_getView('Error');
                $values = $form->getValues();
                $mapper = new Application_Model_BookMapper();
                $mapper->addBookToCourse($values['book_id'], $values['course_id']);

                return $this->_redirector->gotoSimple(
                   'view',
                   'course',
                   null,
                   array('id' => $values['course_id'])
                ); 
            }
        }
        else
        {
            $form->populate(array(
                'course_id'     => $course_id, 
            ));
        }
        // Rewrite breadcrumb
        $page_crse   = $view->navigation()->getContainer()->findOneByLabel('View course');
        $page_crse->setParams(array('id' => $course_id));
        // Push to form
        $view->form = $form;       
    }
    
    /**
     * Add an announcement to course
     */
    public function addannouncementAction()
    {           
        $view = $this->_getView('Add announcement');
        $form = $this->_getAddAnnouncementToCourseForm(); 
        $course_id  = (string)$this->getRequest()->getParam('id');
        if($this->getRequest()->isPost()) 
	{                       
            $formData  = $this->_request->getPost();
            $course_id = $formData['course_id'];
            if($form->isValid($formData)) 
            {
                $view   = $this->_getView('Error');
                $values = $form->getValues();
                $mapper = new Application_Model_AnnouncementMapper();
                
                $announcement = new Application_Model_Announcement();
                $announcement->Id       = $values['announcement_id'];
                $announcement->Title    = $values['announcement_title'];
                $announcement->Text     = $values['announcement_text'];
                $announcement->Active   = $values['announcement_active'];
                $announcement->CourseId = $values['course_id'];

                // Save                
                $mapper->save($announcement);

                return $this->_redirector->gotoSimple(
                   'view',
                   'course',
                   null,
                   array('id' => $values['course_id'])
                ); 
            }
        }
        else
        {
            $form->populate(array(
                'course_id'     => $course_id, 
            ));
        }
        // Rewrite breadcrumb
        $page_crse   = $view->navigation()->getContainer()->findOneByLabel('View course');
        $page_crse->setParams(array('id' => $course_id));
        // Push to form
        $view->form = $form;       
    }
    
    /**
     * Edit a course
     */
    public function editAction()
    {
        $view = $this->_getView('Edit Course');
        $form = $this->_getEditCourseForm();           
        
        if($this->getRequest()->isPost()) 
	{                       
            $formData  = $this->_request->getPost();
                        
            if($form->isValid($formData)) 
            {                
               $this->_saveForm($form);
            }
        }
        else
        {   
           
            $id = (string)$this->getRequest()->getParam('id');
            $course = $this->_getCourseById($id);           

            if($course != null)
            {
                $form->populate(array(
                        'course_id'     => $course->Id,    
                        'course_name'   => $course->Name,
                        'course_description'   => $course->Description,
                ));
            }
            
            $view->form = $form;
        }   
    }

    /**
     * Delete a course
     */
    public function deleteAction()
    {
        $id = (string)$this->getRequest()->getParam('id');        
        $courseMapper = new Application_Model_CourseMapper();
        $courseMapper->delete($id);
        $this->_helper->redirector('index', 'senior');                
    }

    
    /**
     * Save
     */
    private function _saveForm($form)
    {
        $mapper = new Application_Model_CourseMapper();
        $view   = $this->_getView('Fout - Toevoegen');                
        $values = $form->getValues();
        $course = new Application_Model_Course();        
        
        $course->Id             = $values['course_id'];
        $course->Name           = $values['course_name'];
        $course->Description    = $values['course_description'];                                

        $mapper->save($course);                

        $this->_helper->redirector('index', 'senior');  
    }

    
    /**
     * Get the edit form
     *
     * @return Application_Form_AddCourse
     */
    private function _getEditCourseForm()
    {   
        return new Application_Form_EditCourse(array(
            'action' => $this->view->baseUrl() . '/course/edit/',
            'method' => 'post',
        ));
    }
    
    private function _getAddBookToCourseForm()
    {
        return new Application_Form_AddBookToCourse(array(
            'action' => $this->view->baseUrl() . '/course/addbook/',
            'method' => 'post',
        ));
    }
    
    private function _getAddAnnouncementToCourseForm()
    {   
        return new Application_Form_AddAnnouncementToCourse(array(
            'action' => $this->view->baseUrl() . '/course/addannouncement/',
            'method' => 'post',
        ));
    }
    
    /**
     * Get the add form
     *
     * @return Application_Form_EditCourse
     */
    private function _getAddCourseForm()
    {   
        return new Application_Form_AddCourse(array(
            'action' => $this->view->baseUrl() . '/course/add/',
            'method' => 'post',
        ));
    }
    
    /**
     * @param string $id
     * @return Array
     */
    private function _getBook($id)
    {   
        
        $CourseHasBookMapper = new Application_Model_CourseHasBookMapper();
        $BookArray = $CourseHasBookMapper->fetchById($id);

        return $BookArray ;
    }
    
    /**
     * @return Application_Form_DetailsForm
     */
    private function _getCourseDetailsForm()
    {
        return new Application_Form_NameSearch(array(
            'action' => $this->view->baseUrl('course/index'),
            'method' => 'post',
        ));
    }
    
    /**
     * @return Array
     */
    private function _getAllUserHasBooks($id)
    {
        $userHasBookMapper = new Application_Model_UserHasBookMapper();
        $userHasBookArray = $userHasBookMapper->fetchByUserId($id);

        return $userHasBookArray;
    }
    
    /**
     * @return Application_Form_DetailsForm
     */
    /*private function _getAllCourseDetailsForm()
    {
        return new Application_Form_CourseDetails(array(
            'action' => $this->view->baseUrl('course/allcourses'),
            'method' => 'post',
        ));
    }*/
    
    /**
     * @return Array
     */
    private function _getCoursesByName($courseName)
    {
        $courseMapper = new Application_Model_CourseMapper();
        return $courseMapper->fetchByName($courseName);
    }
    
    /**
     * @return Array
     */
    private function _getAllCoursesByUserId($id)
    {
        $courseMapper = new Application_Model_CourseMapper();
        return $courseMapper->fetchByUserId($id);  
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    /**
     * Fetch a course by its ID
     * 
     * @param integer $course_id
     * @return Array
     */
    private function _getCourseById($course_id)
    {
        $mapper = new Application_Model_CourseMapper();
        return $mapper->fetchById($course_id);
    }
    
    /**
     * Get all courses
     *
     * @param integer $page_nr      If you wish to use paging, pass the page-number. To
     *                              disable paging, pass null as value (default) and 
     *                              return all rows.
     * @param integer $nr_results   The number of results per page, defaults to 10.
     * @return Array(Application_Model_Course)
     */
    private function _getCourses($page_nr = null, $nr_results = 0)
    {
        $mapper = new Application_Model_CourseMapper();
        return $mapper->fetchAll($page_nr, $nr_results);
    }
    
    /**
     * Returns the number of courses
     * 
     * @return integer
     */
    private function _countCourses()
    {
        $mapper = new Application_Model_CourseMapper();
        return $mapper->getCount();
    }
    
    /**
     * Get all courses for a user
     *
     * @param integer $user_id
     * @param integer $page_nr      If you wish to use paging, pass the page-number. To
     *                              disable paging, pass null as value (default) and 
     *                              return all rows.
     * @param integer $nr_results   The number of results per page, defaults to 10.
     * @return Array(Application_Model_Course)
     */
    private function _getCoursesByUserId($user_id, $page_nr = null, $nr_results = 0)
    {
        $mapper = new Application_Model_CourseMapper();
        return $mapper->fetchByUserId($user_id, $page_nr, $nr_results);
    }
    
    /**
     * Returns the number of courses a user is following
     * 
     * @param integer $user_id
     * @return integer
     */
    private function _countCoursesByUserId($user_id)
    {
        $mapper = new Application_Model_CourseMapper();
        return $mapper->getCountByUserId($user_id);
    }
    
    /**
     * Get all recent courses
     *
     * @param integer $days         The number of days to fetch back to
     * @param integer $page_nr      If you wish to use paging, pass the page-number. To
     *                              disable paging, pass null as value (default) and 
     *                              return all rows.
     * @param integer $nr_results   The number of results per page, defaults to 10.
     * @return Array(Application_Model_Course)
     */
    private function _getCoursesByRecent($days, $page_nr = null, $nr_results = 0)
    {
        $mapper = new Application_Model_CourseMapper();
        return $mapper->fetchByRecent($days, $page_nr, $nr_results);
    }
    
    /**
     * Returns the number of courses a user is following
     * 
     * @param integer $days         The number of days to fetch back to
     * @return integer
     */
    private function _countCoursesByRecent($days)
    {
        $mapper = new Application_Model_CourseMapper();
        return $mapper->getCountByRecent($days);
    }
    
    /**
     * Get all announcements for a course
     *
     * @param integer $course_id
     * @param integer $page_nr      If you wish to use paging, pass the page-number. To
     *                              disable paging, pass null as value (default) and 
     *                              return all rows.
     * @param integer $nr_results   The number of results per page, defaults to 10.
     * @return Array(Application_Model_Course)
     */
    private function _getAnnouncementsByCourseId($course_id, $page_nr = null, $nr_results = 0)
    {
        $mapper = new Application_Model_AnnouncementMapper();
        return $mapper->fetchByCourseId($course_id, $page_nr, $nr_results);
    }
    
    /**
     * Get the number of announcements for this course
     * 
     * @param integer $course_id
     * @return integer
     */
    private function _countAnnouncementsByCourseId($course_id)
    {
        $mapper = new Application_Model_AnnouncementMapper();
        return $mapper->getCountByCourseId($course_id);
    }
    
    /**
     * Get all books for a course
     *
     * @param integer $course_id
     * @param integer $page_nr      If you wish to use paging, pass the page-number. To
     *                              disable paging, pass null as value (default) and 
     *                              return all rows.
     * @param integer $nr_results   The number of results per page, defaults to 10.
     * @return Array(Application_Model_Course)
     */
    private function _getBooksByCourseId($course_id, $page_nr = null, $nr_results = 0)
    {
        $mapper = new Application_Model_BookMapper();
        return $mapper->fetchByCourseId($course_id, $page_nr, $nr_results);
    }
    
    /**
     * Get the number of books for this course
     * 
     * @param integer $course_id
     * @return integer
     */
    private function _countBooksByCourseId($course_id)
    {
        $mapper = new Application_Model_BookMapper();
        return $mapper->getCountByCourseId($course_id);
    }
    
    /**
     * Add a course to a user's follow list
     * 
     * @param integer $course_id
     * @param integer $user_id 
     */
    private function _addCourseToFollowList($course_id, $user_id)
    {
        $mapper = new Application_Model_UserMapper();
        $mapper->addCourseToUser($course_id, $user_id);
    }
    
    /**
     * Add a course to a user's follow list
     * 
     * @param integer $course_id
     * @param integer $user_id 
     */
    private function _removeCourseFromFollowList($course_id, $user_id)
    {
        $mapper = new Application_Model_UserMapper();
        $mapper->deleteCourseFromUser($course_id, $user_id);
    }

    /**
     * Loops through a list of custom objects, passing each object to the partial.
     * The end result is a html-render of the all the partials.
     *
     * @param string $partial
     * @param Array $objects
     * @return string
     */
    private function _loopPartial($partial, $objects, $extravars=null)
    {
        $result = array();
        $count  = 0;
        if(count($objects))
        {
            foreach($objects as $object)
            {
                $count++;
                $vars       = array(
                    'object'    => $object,
                    'count'     => $count,
                );
                
                if(is_array($extravars))
                    $vars = array_merge($extravars, $vars);
                
                $result[]   = $this->_getView("")->partial('partials/'.$partial.'.phtml', $vars);
            }
        }
        
        return implode("\n", $result);
    }

    /**
     * Get the HTML pager for a list that requires pagination
     *
     * @param int $page_nr
     * @param int $total_pages
     * @param string $base_url
     * @param string $page_var
     * @return string 
     */
    private function _fetchPager($current_page, $total_pages, $base_url, $page_var)
    {
        $view   = $this->_getView("");
        $vars   = array(
            'cur_page'      => $current_page,
            'nr_of_pages'   => ceil($total_pages),
            'base_url'      => $base_url,
            'page_var'      => $page_var,
        );
        
        return $view->partial('partials/pager.phtml', $vars);
    }

    /**
     * This returns the view for this controller.
     *
     * @param string $title
     * @return Zend_View
     */
    private function _getView($title)
    {
        $view = $this->view;
        $view->title = $title;
        $view->headTitle($view->title, 'PREPEND');

        return $view;
    }
}